//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "common.h"
#include "aligned_buffer.h"


#define FC_MAKE_TRAIT(_class, _trait) \
	namespace fc { \
	template<> struct _trait<_class > : true_type { }; \
	}

#define FC_REMOVE_TRAIT(_class, _trait) \
	namespace fc { \
	template<> struct _trait<_class > : false_type { }; \
	}


FC_NAMESPACE_BEGIN


template <class T, T v> struct integral_constant
{
	static const T value = v;
	typedef T value_type;
	typedef integral_constant<T, v> type;
};

typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;


template <class T> struct is_integral : false_type { };
template<> struct is_integral<bool> : true_type { };
template<> struct is_integral<char> : true_type { };
template<> struct is_integral<signed char> : true_type { };
template<> struct is_integral<unsigned char> : true_type { };
template<> struct is_integral<short> : true_type { };
template<> struct is_integral<unsigned short> : true_type { };
template<> struct is_integral<int> : true_type { };
template<> struct is_integral<unsigned int> : true_type { };
template<> struct is_integral<long> : true_type { };
template<> struct is_integral<unsigned long> : true_type { };
template<> struct is_integral<long long> : true_type { };
template<> struct is_integral<unsigned long long> : true_type { };

template <class T> struct is_integral<const T> : is_integral<T> { };
template <class T> struct is_integral<volatile T> : is_integral<T> { };
template <class T> struct is_integral<const volatile T> : is_integral<T> { };

template <class T> struct is_floating_point : false_type { };
template<> struct is_floating_point<float> : true_type { };
template<> struct is_floating_point<double> : true_type { };
template<> struct is_floating_point<long double> : true_type { };

template <class T> struct is_floating_point<const T> : is_floating_point<T> { };
template <class T> struct is_floating_point<volatile T> : is_floating_point<T> { };
template <class T> struct is_floating_point<const volatile T> : is_floating_point<T> { };

/*
template <class T> struct is_char : false_type { };
template<> struct is_char<char> : true_type { };
template<> struct is_char<unsigned char> : true_type { };
template <class T> struct is_char<const T> : is_char<T> { };
*/

//template <class T, size_t N> struct is_sizeof : false_type { };
//template <class T, size_t N> struct is_sizeof : false_type { };
template <class T, size_t N> struct is_sizeof : integral_constant <bool, (sizeof(T) == N)> { };


template <class T> struct is_pointer : false_type { };
template <class T> struct is_pointer<T*> : true_type { };
template <class T> struct is_pointer<T**> : true_type { };
template <class T> struct is_pointer<const T*> : true_type { };

template<class T> struct is_reference : false_type {};
template<class T> struct is_reference<T&> : true_type {};
template<class T> struct is_reference<const T&> : true_type {};

template<class T> struct is_const : false_type {};
template<class T> struct is_const<const T> : true_type {};

template <class T> struct is_pod : integral_constant
	<bool, (is_integral<T>::value || is_floating_point<T>::value || is_pointer<T>::value)> { };
template <class T> struct is_pod<const T> : is_pod<T> { };

template <class T> struct is_fundamental : integral_constant 
	<bool, (is_integral<T>::value || is_floating_point<T>::value)> { };
template <class T> struct is_fundamental<const T> : is_fundamental<T> { };

template <class T> struct is_scalar : is_pod<T> { };
template <class T> struct is_scalar<const T> : is_scalar<T> { };

template <class T> struct has_trivial_constructor : is_pod<T> { };
template <class T> struct has_trivial_constructor<const T> : has_trivial_constructor<T> { };

template <class T> struct has_trivial_copy : is_pod<T> { };
template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };

template <class T> struct has_trivial_assign : is_pod<T> { };

template <class T> struct has_trivial_destructor : is_pod<T> { };
template <class T> struct has_trivial_destructor<const T> : has_trivial_destructor<T> { };


// is_true_type
template <bool T> struct is_true_type : false_type { };
template <> struct is_true_type<true> : true_type { };

// is_binary_copyable
template <bool T1, bool T2, bool T3 = true, bool T4 = true> struct is_binary_copyable : false_type { };
template <> struct is_binary_copyable<true, true, true, true> : true_type { };

// is_binary_comparable
template <bool T1, bool T2, bool T3 = true, bool T4 = true> struct is_binary_comparable : false_type { };
template <> struct is_binary_comparable<true, true, true, true> : true_type { };


// type_select
template <bool Condition, class TrueType, class FalseType> struct type_select { typedef TrueType type; };
template <class TrueType, class FalseType> struct type_select<false, TrueType, FalseType> { typedef FalseType type; }; 



FC_NAMESPACE_END

